package com.hyt.it.ogt.kq.service.gov.service.impl;

import com.alibaba.excel.EasyExcel;
import com.hyt.core.base.BaseServiceImpl;
import com.hyt.it.ogt.kq.common.gov.constant.ResponseCode;
import com.hyt.it.ogt.kq.common.gov.constant.StringCodeEnum;
import com.hyt.it.ogt.kq.common.config.exception.KqException;
import com.hyt.it.ogt.kq.service.gov.mapper.SysAreaMapper;
import com.hyt.it.ogt.kq.service.gov.model.entity.SysArea;
import com.hyt.it.ogt.kq.service.gov.model.entity.Task;
import com.hyt.it.ogt.kq.service.gov.model.excel.AreaSheet;
import com.hyt.it.ogt.kq.service.gov.model.excel.listener.AreaListener;
import com.hyt.it.ogt.kq.service.gov.service.IOfficeAreaService;
import com.hyt.it.ogt.kq.service.gov.service.IOfficeCandidateAreaService;
import com.hyt.it.ogt.kq.service.gov.service.ISysAreaService;
import com.hyt.it.ogt.kq.service.gov.service.ITaskService;
import com.hyt.it.ogt.kq.common.gov.utils.TextUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.TreeSet;
import java.util.stream.Collectors;

/**
 * <p>
 * 系统级行政区划表 服务实现类
 * </p>
 *
 * @author huangyh
 * @since 2021-04-06
 */
@Slf4j
@Service
public class SysAreaServiceImpl extends BaseServiceImpl<SysAreaMapper, SysArea> implements ISysAreaService {

    @Resource
    private IOfficeAreaService iOfficeAreaService;

    @Resource
    private IOfficeCandidateAreaService iOfficeCandidateAreaService;
    @Resource
    private ITaskService iTaskService;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void importSysArea(MultipartFile file,String initType) throws KqException, IOException {

        //删除数据
        this.lambdaUpdate()
                .set(SysArea::getDelFlag,true)
                .update();

        //校验excel文件
        this.excelVerify(file);
        //校验当前是否存在系统级区域数据
        this.checkSysAreaExist();
        //读取excel文件
        List<AreaSheet> areaSheetList = this.readExcel(file);
        //校验excel内容
        this.contentVerify(areaSheetList);
        //组装数据
        List<SysArea> sysAreaList = this.convertSysArea(areaSheetList);
        //保存系统区域数据
        this.saveSysArea(sysAreaList);
        if ("2".equals(initType)) {
            iOfficeAreaService.removeOfficeArea();
            iOfficeCandidateAreaService.removeOfficeCandidateArea();
            List<Task> list = iTaskService.lambdaQuery()
                    .eq(Task::getDelFlag,false)
                    .groupBy(Task::getOfficeId)
                    .select(Task::getOfficeId)
                    .list();
            list.stream().forEach(task -> {
                iOfficeAreaService.initOfficeArea(task.getOfficeId());
                iOfficeCandidateAreaService.initOfficeCandidateArea(task.getOfficeId());
            });
        }

    }

    /**
     * 校验excel文件
     * @param file excel文件
     * @throws KqException 异常
     */
    private void excelVerify(MultipartFile file) throws KqException {
        if (file.isEmpty()) {
            //导入文件不存在
            throw new KqException(ResponseCode.IMPORT_FILE_NOT_EXIST.getCode(),
                    ResponseCode.IMPORT_FILE_NOT_EXIST.getMsg());
        }
        String fileName = file.getOriginalFilename();
        if (fileName == null) {
            //导入文件类型错误
            throw new KqException(ResponseCode.WRONG_FILE_TYPE.getCode(),
                    ResponseCode.WRONG_FILE_TYPE.getMsg());
        }
        String ext = FilenameUtils.getExtension(fileName);
        if (!ext.equalsIgnoreCase(StringCodeEnum.EXCEL_XLS.getCode())
                && !ext.equalsIgnoreCase(StringCodeEnum.EXCEL_XLSX.getCode())) {
            //导入文件类型错误
            throw new KqException(ResponseCode.WRONG_FILE_TYPE.getCode(),
                    ResponseCode.WRONG_FILE_TYPE.getMsg());
        }
    }

    /**
     * 校验当前是否存在系统级区域数据
     * @throws KqException 异常
     */
    private void checkSysAreaExist() throws KqException {
        Integer count = this.lambdaQuery()
                .eq(SysArea::getDelFlag, false)
                .count();
        if (count > 0) {
            //当前存在系统级区域数据，无法导入
            throw new KqException(ResponseCode.HAS_SYS_AREA.getCode(),
                    ResponseCode.HAS_SYS_AREA.getMsg());
        }
    }

    /**
     * 读取excel文件
     * @param file excel文件
     * @return excel内容
     * @throws IOException IO异常
     */
    private List<AreaSheet> readExcel(MultipartFile file) throws IOException {
        AreaListener areaListener = new AreaListener();
        EasyExcel.read(file.getInputStream(), AreaSheet.class, areaListener)
                .sheet().doRead();
        return areaListener.getDataList();
    }

    /**
     * 校验excel内容
     * @param areaSheetList excel内容
     * @throws KqException 异常
     */
    private void contentVerify(List<AreaSheet> areaSheetList) throws KqException {
        if (CollectionUtils.isEmpty(areaSheetList)) {
            throw new KqException(ResponseCode.SYS_AREA_EXCEL_CONTENT_ERROR.getCode(), "导入的excel为空");
        }
        for (int i = 0; i < areaSheetList.size(); i++) {
            AreaSheet area = areaSheetList.get(i);
            int rowNumber = i + 1;
            if (StringUtils.isEmpty(area.getCountryName())) {
                throw new KqException(ResponseCode.SYS_AREA_EXCEL_CONTENT_ERROR.getCode(), "第" + rowNumber + "行数据国名称为空");
            }
            if (!TextUtil.isLongNum(area.getCityCode())) {
                throw new KqException(ResponseCode.SYS_AREA_EXCEL_CONTENT_ERROR.getCode(), "第" + rowNumber + "行数据国编码格式不正确");
            }
            if (StringUtils.isEmpty(area.getProvinceName())) {
                throw new KqException(ResponseCode.SYS_AREA_EXCEL_CONTENT_ERROR.getCode(), "第" + rowNumber + "行数据省名称为空");
            }
            if (!TextUtil.isLongNum(area.getProvinceCode())) {
                throw new KqException(ResponseCode.SYS_AREA_EXCEL_CONTENT_ERROR.getCode(), "第" + rowNumber + "行数据省编码格式不正确");
            }
            // 完善各字段校验
        }

    }

    /**
     * 组装区域数据
     * @param areaSheetList excel内容
     * @return 组装结果
     */
    private List<SysArea> convertSysArea(List<AreaSheet> areaSheetList) {
        //筛选国数据
        List<AreaSheet> countryList = areaSheetList.stream()
                .collect(Collectors.collectingAndThen(
                        Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(AreaSheet::getCountryCode))), ArrayList::new
                ));
        //筛选省数据
        List<AreaSheet> provinceList = areaSheetList.stream()
                .collect(Collectors.collectingAndThen(
                        Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(AreaSheet::getProvinceCode))), ArrayList::new
                ));
        //筛选市数据
        List<AreaSheet> cityList = areaSheetList.stream()
                .collect(Collectors.collectingAndThen(
                        Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(AreaSheet::getCityCode))), ArrayList::new
                ));
        //筛选区县数据
        List<AreaSheet> districtList = areaSheetList.stream()
                .collect(Collectors.collectingAndThen(
                        Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(AreaSheet::getDistrictCode))), ArrayList::new
                ));
        //组装国
        List<SysArea> sysAreaList = countryList.stream().map(country -> {
            SysArea sysArea = new SysArea();
            sysArea.setAreaId(country.getCountryCode())
                    .setName(country.getCountryName())
                    .setType("1");
            return sysArea;
        }).collect(Collectors.toList());
        //组装省
        List<SysArea> provinceAreaList = provinceList.stream().map(province -> {
            SysArea sysArea = new SysArea();
            sysArea.setAreaId(province.getProvinceCode())
                    .setParentId(province.getCountryCode())
                    .setParentIds(province.getCountryCode())
                    .setName(province.getProvinceName())
                    .setType("2");
            return sysArea;
        }).collect(Collectors.toList());
        sysAreaList.addAll(provinceAreaList);
        //组装市
        List<SysArea> cityAreaList = cityList.stream().map(city -> {
            SysArea sysArea = new SysArea();
            sysArea.setAreaId(city.getCityCode())
                    .setParentId(city.getProvinceCode())
                    .setParentIds(StringUtils.join(city.getCountryCode(), ",", city.getProvinceCode()))
                    .setName(city.getCityName())
                    .setType("3");
            return sysArea;
        }).collect(Collectors.toList());
        sysAreaList.addAll(cityAreaList);
        //组装区县
        List<SysArea> districtAreaList = districtList.stream().map(district -> {
            SysArea sysArea = new SysArea();
            sysArea.setAreaId(district.getDistrictCode())
                    .setParentId(district.getCityCode())
                    .setParentIds(StringUtils.join(district.getCountryCode(), ",", district.getProvinceCode(), ",", district.getCityCode()))
                    .setName(district.getDistrictName())
                    .setType("4");
            return sysArea;
        }).collect(Collectors.toList());
        sysAreaList.addAll(districtAreaList);
        return sysAreaList;
    }

    /**
     * 保存系统区域数据
     * @param sysAreaList 系统区域数据
     * @throws KqException 异常
     */
    private void saveSysArea(List<SysArea> sysAreaList) throws KqException {
        if (!saveBatch(sysAreaList)) {
            //插入系统区域表失败
            throw new KqException(ResponseCode.IMPORT_SYS_AREA_EXCEPTION.getCode(),
                    ResponseCode.IMPORT_SYS_AREA_EXCEPTION.getMsg());
        }
    }

}
